package com.aaron.nettystudy.coding;


import com.aaron.nettystudy.serialize.Serializer;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.ByteToMessageDecoder;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;

import java.util.List;

/**
 * @ClassName kyroDecoder
 * @description: 解码，调用序列化方法，将对象转换为字节数组。对象最后保存在list数组中。
 * @author: 荣燊
 * @create: 2021-05-14 22:26
 **/
@AllArgsConstructor
@Slf4j
//ByteToMessageDecoder继承的是ChannelInboundHandlerAdapter，入站，那么必须实现Decode解码方法了。将字节数组转化为对象。
public class KyroDecoder extends ByteToMessageDecoder {
    private final Serializer serializer; //参数一，序列化与反序列化的接口
    private final Class<?> genericClass; //参数二，序列化的类型

    //对象在序列化之后的字节数组，其大小的描述信息存储在ByteBuf的头部，4字节
    private static final int BODY_LENGTH = 4;

    //入站，实现解码器，将字节数组转化为对象
    //参数一：上下文，参数二：ByteBuf，参数三：list集合存放处理后的结果，可以传递给下一个ChannelInboundHandler处理
    @Override
    protected void decode(ChannelHandlerContext channelHandlerContext, ByteBuf byteBuf, List<Object> list) throws Exception {
        if (byteBuf.readableBytes() >= BODY_LENGTH) {
            //标记当前readIndex的位置，以便后面重置readIndex的时候使用
            byteBuf.markReaderIndex();
            //读取头信息，4个字节的。判断数据的大小是否合法。
            int datalength = byteBuf.readInt();
            if (datalength < 0 || byteBuf.readableBytes() < 0) {
                log.error("data length or byteBuf readableBytes is not valid");
                return;
            }
            //如果可读字节数小于消息长度的话，说明是不完整的消息，重置readIndex
            if (byteBuf.readableBytes() < datalength) {
                byteBuf.resetReaderIndex();
                return;
            }
            //经过以上的判断说明没问题，可以将读取的数据放到字节数组中
            byte[] body = new byte[datalength];
            byteBuf.readBytes(body);

            //再将字节数组做反序列化处理，将字节数组body转换为genericClass类的对象
            Object obj = serializer.deserialize(body, genericClass);
            //将解析的对象，加入到list集合中。
            list.add(obj);
            log.info("success decode ByteBuf to Object，解码成功");
        }
    }
}
